package com.caiwl.springboot.pro;

import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author caiwl
 * @date 2020/5/22 15:54
 */
@SpringBootApplication
@RestController
public class InitializrProApplication {
    public static void main(String[] args) {
        SpringApplication.run(InitializrProApplication.class, args);
    }

    @GetMapping("/")
    public String home() {
        return "Hello World";
    }

    @RequestMapping("/generate")
    public void generate(String project, String language, String springboot,
                         String groupId, String artifactId, String projectName, String description,
                         String packageName, String packaging, String javaVersion,
                         HttpServletResponse response) {
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_30);
        configuration.setClassForTemplateLoading(InitializrProApplication.class, "/templates");
        configuration.setDefaultEncoding("UTF-8");
        // 项目根目录
        String root = System.getProperty("user.dir");

        buildPom(configuration, root, groupId, artifactId, packaging, projectName, description, javaVersion, springboot);
        buildApplication(configuration, root, packageName, projectName);

        response.setHeader("Content-Disposition","attachment; filename=" + projectName + ".zip");
        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
            zip(new File(root + "/target/" + projectName), zipOut, projectName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void buildPom(Configuration configuration, String root,
                          String groupId, String artifactId, String packaging, String name, String description,
                          String javaVersion, String springboot) {
        try {
            Map<String, Object> dataModel = new HashMap<>(7);
            dataModel.put("groupId", groupId);
            dataModel.put("artifactId", artifactId);
            dataModel.put("packaging", packaging);
            dataModel.put("name", name);
            dataModel.put("description", description);
            dataModel.put("javaVersion", javaVersion);
            dataModel.put("springboot", springboot);
            Template template = configuration.getTemplate("pom.ftl");
            template.process(dataModel, new FileWriter(newFile(root + "/target/" + name + "/pom.xml")));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void buildApplication(Configuration configuration, String root,
                                  String packageName, String name) {
        try {
            Map<String, Object> dataModel = new HashMap<>(2);
            dataModel.put("packageName", packageName);
            String prefix = name.substring(0, 1).toUpperCase() + name.substring(1);
            dataModel.put("projectName", prefix);
            Template template = configuration.getTemplate("Application.ftl");
            template.process(dataModel, new FileWriter(newFile(root + "/target/" + name + "/" + packageName.replaceAll("\\.", "/") + "/" + prefix + "Application.java")));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void zip(File file, ZipOutputStream zipOut, String entryName) throws IOException {
        int read;
        byte[] buf = new byte[1024 * 10];
        BufferedInputStream bufferedInputStream;
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            // 空目录
            if (files == null || files.length == 0) {
                zipOut.putNextEntry(new ZipEntry(entryName + "/"));
                zipOut.closeEntry();
            } else {
                for (File child : files) {
                    zip(child, zipOut, entryName + "/" + child.getName());
                }
            }
        } else {
            zipOut.putNextEntry(new ZipEntry(entryName));
            bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
            while ((read = bufferedInputStream.read(buf)) != -1) {
                zipOut.write(buf, 0, read);
            }
            zipOut.closeEntry();
            bufferedInputStream.close();
        }
    }

    private File newFile(String pathname) throws IOException {
        File file = new File(pathname);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        if (!file.exists()) {
            file.createNewFile();
        }
        return  file;
    }
}
